/*
 * Basic CDNET Communication Example
 * 
 * This example demonstrates basic CDNET Layer 0 and Layer 1 communication.
 * 
 * Hardware connections:
 * - Connect TX1 to RX2 and RX1 to TX2
 * - Connect GND together
 * - Use RS-485 transceivers for long distance communication
 */

#include <SimpleCDNET.h>

// Create CDNET instance
SimpleCDNET cdnet;

// Device address - change this for each device
const uint8_t DEVICE_ADDRESS = 0x01;

// Destination address for communication
const uint8_t DEST_ADDRESS = 0x02;

// CDNET ports
const uint8_t L0_PORT = 0x10;      // Data port for Layer 0
const uint16_t L1_PORT = 0x1000;   // Data port for Layer 1

void setup() {
    Serial.begin(115200);
    while (!Serial) {
        ; // wait for serial port to connect
    }
    
    Serial.println("SimpleCDNET Basic Example");
    Serial.print("Device Address: 0x");
    Serial.println(DEVICE_ADDRESS, HEX);
    
    // Initialize CDNET with Serial1 (pins 18/19 on Arduino Mega)
    cdnet.begin(&Serial1, DEVICE_ADDRESS);
    cdnet.setBaudRate(115200);
    
    Serial.println("CDNET initialized");
    Serial.println("Ready to send/receive data");
    Serial.println("Commands:");
    Serial.println("  '0' - Send L0 test data");
    Serial.println("  '1' - Send L1 test data");
    Serial.println("  'r' - Read received data");
    Serial.println("  'a' - Check availability");
}

void loop() {
    cdnet.update();  // Process incoming data
    
    if (Serial.available()) {
        char cmd = Serial.read();
        
        switch (cmd) {
            case '0':
                sendL0TestData();
                break;
                
            case '1':
                sendL1TestData();
                break;
                
            case 'r':
            case 'R':
                readReceivedData();
                break;
                
            case 'a':
            case 'A':
                checkAvailability();
                break;
                
            default:
                Serial.println("Unknown command");
                break;
        }
    }
    
    // Automatically process received data
    if (cdnet.available()) {
        processReceivedData();
    }
}

void sendL0TestData() {
    uint8_t testData[] = {0xCA, 0xFE, 0xBA, 0xBE};
    
    Serial.print("Sending L0 test data to 0x");
    Serial.print(DEST_ADDRESS, HEX);
    Serial.print(" on port 0x");
    Serial.print(L0_PORT, HEX);
    Serial.print(": ");
    
    for (uint8_t i = 0; i < sizeof(testData); i++) {
        Serial.print("0x");
        if (testData[i] < 0x10) Serial.print("0");
        Serial.print(testData[i], HEX);
        Serial.print(" ");
    }
    Serial.println();
    
    cdnet.sendL0(DEST_ADDRESS, L0_PORT, testData, sizeof(testData));
    Serial.println("L0 data sent");
}

void sendL1TestData() {
    uint8_t testData[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
    
    Serial.print("Sending L1 test data to 0x");
    Serial.print(DEST_ADDRESS, HEX);
    Serial.print(" on port 0x");
    Serial.print(L1_PORT, HEX);
    Serial.print(": ");
    
    for (uint8_t i = 0; i < sizeof(testData); i++) {
        Serial.print("0x");
        if (testData[i] < 0x10) Serial.print("0");
        Serial.print(testData[i], HEX);
        Serial.print(" ");
    }
    Serial.println();
    
    cdnet.sendL1(DEST_ADDRESS, L1_PORT, testData, sizeof(testData));
    Serial.println("L1 data sent");
}

void readReceivedData() {
    uint8_t src;
    uint8_t port8;
    uint16_t port16;
    uint8_t buffer[64];
    uint8_t len;
    
    // Try L0 first
    len = cdnet.readL0(&src, &port8, buffer, sizeof(buffer));
    if (len > 0) {
        Serial.print("Received L0 data from 0x");
        Serial.print(src, HEX);
        Serial.print(" on port 0x");
        Serial.print(port8, HEX);
        Serial.print(": ");
        
        for (uint8_t i = 0; i < len; i++) {
            Serial.print("0x");
            if (buffer[i] < 0x10) Serial.print("0");
            Serial.print(buffer[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
        return;
    }
    
    // Try L1
    len = cdnet.readL1(&src, &port16, buffer, sizeof(buffer));
    if (len > 0) {
        Serial.print("Received L1 data from 0x");
        Serial.print(src, HEX);
        Serial.print(" on port 0x");
        Serial.print(port16, HEX);
        Serial.print(": ");
        
        for (uint8_t i = 0; i < len; i++) {
            Serial.print("0x");
            if (buffer[i] < 0x10) Serial.print("0");
            Serial.print(buffer[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
        return;
    }
    
    Serial.println("No data available");
}

void checkAvailability() {
    bool available = cdnet.available();
    Serial.print("Data available: ");
    Serial.println(available ? "Yes" : "No");
}

void processReceivedData() {
    uint8_t src;
    uint8_t port8;
    uint16_t port16;
    uint8_t buffer[64];
    uint8_t len;
    
    // Process L0 packets
    len = cdnet.readL0(&src, &port8, buffer, sizeof(buffer));
    if (len > 0) {
        Serial.print("Auto: L0 from 0x");
        Serial.print(src, HEX);
        Serial.print(" port 0x");
        Serial.print(port8, HEX);
        Serial.print(" data: ");
        
        for (uint8_t i = 0; i < len; i++) {
            Serial.print("0x");
            if (buffer[i] < 0x10) Serial.print("0");
            Serial.print(buffer[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
    }
    
    // Process L1 packets
    len = cdnet.readL1(&src, &port16, buffer, sizeof(buffer));
    if (len > 0) {
        Serial.print("Auto: L1 from 0x");
        Serial.print(src, HEX);
        Serial.print(" port 0x");
        Serial.print(port16, HEX);
        Serial.print(" data: ");
        
        for (uint8_t i = 0; i < len; i++) {
            Serial.print("0x");
            if (buffer[i] < 0x10) Serial.print("0");
            Serial.print(buffer[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
    }
}